package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.UserCacheConstant;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.dto.DeviceServiceDataPageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private Client client;
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 查询物联网平台同步产品列表
     * @return
     */
    @Override
    public List<ProductVo> getProductList(){
        //创建查询条件
        QueryProductListRequest request = new QueryProductListRequest();
        //设置查询的产品实例编号
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setCurrentPage(1);
        request.setPageSize(50);

        QueryProductListResponse productList;
        try {
            //连接Aliyun IOT官方平台获取产品信息
            productList = client.queryProductList(request);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }

        //判读连接请求是否成功
        if (!productList.getBody().success) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }

        //将产品数据存入redis中
        String jsonString = JSON.toJSONString(productList.getBody().getData().getList().productInfo);
        String key = UserCacheConstant.IOT_ALL_PRODUCT;
        redisTemplate.opsForValue().set(key,jsonString);

        //转成集合返回
        List<ProductVo> productVos = JSONArray.parseArray(jsonString, ProductVo.class);

        return productVos;
    }

    /**
     * 查询所有产品列表
     * @return
     */
    @Override
    public List<ProductVo> getAllProduct() {
        //从redis中查询所有产品
        String products = redisTemplate.opsForValue().get(UserCacheConstant.IOT_ALL_PRODUCT);
        //通过JSONArray将集合JSON字符串转为集合
        List<ProductVo> productVos = JSONArray.parseArray(products, ProductVo.class);

        return productVos;
    }

    /**
     * 注册物联设备
     * @param deviceDto
     */
    @Override
    public void addRegisterDevice(DeviceDto deviceDto) {
        if (deviceDto == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }
        //1.1、查询设备名称是否重复
        int count = deviceMapper.countDeviceDuplicate(deviceDto.getDeviceName());
        if (count >0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //1.2、查询该老人/位置是否绑定该设备
        Boolean result = deviceMapper.countByBindingLocationANDProductKey(deviceDto.getBindingLocation(),deviceDto.getProductKey());
        if (result) {
            throw new BaseException(BasicEnum.RE_SELECT_PRODUCT);
        }

        //获取绑定产品设备参数
        RegisterDeviceRequest deviceRequest = deviceDto.getRegisterDeviceRequest();
        deviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        //2、调用aliyun接口注册设备
        RegisterDeviceResponse registerDeviceResponse;
        try {
            registerDeviceResponse = client.registerDevice(deviceRequest);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        //判断返回信息是否成功
        if (!registerDeviceResponse.getBody().success) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        //获取注册设备id
        String iotId = registerDeviceResponse.getBody().getData().getIotId();

        //3、查询产品名称
        QueryProductRequest request = new QueryProductRequest();
        request.setProductKey(deviceDto.getProductKey());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductResponse queryProduct;
        try {
            queryProduct = client.queryProduct(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }

        //判断返回信息是否成功
        if (!queryProduct.getBody().success) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        //获取产品名称
        String productName = queryProduct.getBody().getData().getProductName();

        //4、如果设备绑定的是老人随身设备，则物理位置设置为-1
        if (deviceDto.getLocationType() == 0) {
            deviceDto.setPhysicalLocationType(-1);
        }

        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setHaveEntranceGuard(0); //不包含门禁
        device.setProductName(productName);
        device.setIotId(iotId); //设置设备id

        //5、保存注册的设备信息到数据库中
        try {
            deviceMapper.insertDevice(device);
        } catch (Exception e) {
            //6、如果保存失败就删除iot的注册设备
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setDeviceName(deviceDto.getDeviceName());
            deleteDeviceRequest.setIotId(iotId);
            deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteDeviceRequest.setProductKey(deviceDto.getProductKey());
            try {
                client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
            
            throw new BaseException(BasicEnum.RE_SELECT_PRODUCT);
        }

    }

    /**
     * 分页查询设备列表
     * @param pageQueryDto
     * @return
     */
    @Override
    public PageResponse<DeviceVo> getDeviceList(DevicePageQueryDto pageQueryDto) {
        if (pageQueryDto == null || pageQueryDto.getPageNum() == null || pageQueryDto.getPageSize() == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }

        //设置页码条件
        PageHelper.startPage(pageQueryDto.getPageNum(),pageQueryDto.getPageSize());
        //查询设备列表
        List<DeviceVo> deviceVos = deviceMapper.selectDevicePage(pageQueryDto);

        Page<DeviceVo> page = (Page<DeviceVo>) deviceVos;

        return PageResponse.of(page,DeviceVo.class);
    }

    //查询设备详细数据
    @Override
    public DeviceVo getDeviceDetail(DeviceDto deviceDto) {
        if (deviceDto == null || deviceDto.getProductKey() == null || deviceDto.getIotId() == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }

        //1、查询数据库设备信息
        DeviceVo deviceVo = deviceMapper.selectDeviceDetail(deviceDto.getIotId());

        //2、调用aliyun iot接口查询设备详情
        QueryDeviceDetailRequest queryDeviceDetailRequest = new QueryDeviceDetailRequest();
        queryDeviceDetailRequest.setDeviceName(deviceVo.getDeviceName());
        queryDeviceDetailRequest.setIotId(deviceDto.getIotId());
        queryDeviceDetailRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryDeviceDetailRequest.setProductKey(deviceDto.getProductKey());
        QueryDeviceDetailResponse response;
        try {
            response = client.queryDeviceDetail(queryDeviceDetailRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //判断调用接口是否成功
        if(!response.getBody().success) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        //3、合并封装数据
        deviceVo.setDeviceSecret(response.getBody().getData().getDeviceSecret()); //设备密钥
        deviceVo.setStatus(response.getBody().getData().getStatus()); //设备状态
        deviceVo.setNickname(response.getBody().getData().getNickname()); //备注名称
        deviceVo.setIpAddress(response.getBody().getData().getIpAddress()); //设备ip地址
        deviceVo.setRegion(response.getBody().getData().getRegion()); //设备所在地区
        deviceVo.setFirmwareVersion(response.getBody().getData().getFirmwareVersion()); //固件版本
        deviceVo.setGmtActive(response.getBody().getData().getGmtActive()); //设备激活时间
        deviceVo.setGmtCreate(response.getBody().getData().getGmtCreate()); //设备的创建时间

        return deviceVo;
    }

    /**
     * 查询指定设备的物模型运行状态
     * @return
     */
    @Override
    public QueryDevicePropertyStatusResponse getDeviceStatus(DeviceDto deviceDto) {
        if (deviceDto == null || deviceDto.getProductKey() == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }

        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setDeviceName(deviceDto.getDeviceName());
        request.setProductKey(deviceDto.getProductKey());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse deviceStatus;
        try {
            deviceStatus = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        //判断调用接口是否成功
        if (!deviceStatus.getBody().success) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        return deviceStatus;
    }

    /**
     * 查看指定产品的已发布物模型中的功能定义详情
     * @param deviceDto
     * @return
     */
    @Override
    public QueryThingModelPublishedResponse getModelPublished(DeviceDto deviceDto) {
        if (deviceDto == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }

        QueryThingModelPublishedRequest request = new QueryThingModelPublishedRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        QueryThingModelPublishedResponse response;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }

        //判断调用接口是否成功
        if (!response.getBody().success) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }

        return response;
    }

    /**
     * 修改设备备注名称接口
     * @param deviceDto
     */
    @Override
    public void UpdateDevice(DeviceDto deviceDto) {
        if (deviceDto == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }
        //先查询设备是否存在
        int count = deviceMapper.countDeviceDuplicate(deviceDto.getDeviceName());
        if (count != 1) {
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }

        //1、调用接口修改iot设备
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        //1.1、设置请求的参数列表
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        //1.2、创建要修改的设备集合
        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> deviceNicknameInfo = new ArrayList<>();
        //1.2.1、创建要修改的设备对象
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        //1.2.2、设置修改的设备信息
        nicknameInfo.setDeviceName(deviceDto.getDeviceName());
        nicknameInfo.setNickname(deviceDto.getNickname());
        nicknameInfo.setIotId(deviceDto.getIotId());
        nicknameInfo.setProductKey(deviceDto.getProductKey());
        //1.2.3、将对象添加到集合中
        deviceNicknameInfo.add(nicknameInfo);
        request.setDeviceNicknameInfo(deviceNicknameInfo);

        BatchUpdateDeviceNicknameResponse response;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        //2、判断调用接口是否成功
        if (!response.getBody().success) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        //3、更新数据库device表的设备信息
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        deviceMapper.UpdateDevice(device);

    }

    /**
     * 删除设备
     * @param deviceDto
     */
    @Override
    public void deleteDevice(DeviceDto deviceDto) {
        if (deviceDto == null || deviceDto.getProductKey() == null || deviceDto.getIotId() == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }

        //1、调用iot删除接口
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setProductKey(deviceDto.getProductKey());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setIotId(deviceDto.getIotId());
        DeleteDeviceResponse response;
        try {
            response = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }

        //2、判断调用接口是否成功
        if (!response.getBody().success) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        //3、删除数据库表中的设备信息
        deviceMapper.deleteDeviceByIotId(deviceDto.getIotId());
    }

    /**
     * 分页查询设备服务调用数据
     * @param pageQueryDto
     * @return
     */
    @Override
    public QueryDeviceServiceDataResponse getServiceDataPage(DeviceServiceDataPageQueryDto pageQueryDto) {
        if (pageQueryDto == null) {
            throw new BaseException(BasicEnum.PARAM_ERROR);
        }
        pageQueryDto.setPageSize(5);

        //查询设备信息
        DeviceVo deviceVo = deviceMapper.selectDeviceDetail(pageQueryDto.getIotId());

        //设置查询条件
        QueryDeviceServiceDataRequest request = new QueryDeviceServiceDataRequest();
        request.setPageSize(pageQueryDto.getPageSize());
        request.setStartTime(pageQueryDto.getStartTime());
        request.setEndTime(pageQueryDto.getEndTime());
        request.setIotId(pageQueryDto.getIotId());
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceVo.getProductKey()); //设置指定产品
        request.setDeviceName(deviceVo.getDeviceName());

        //调用iot查询设备服务数据接口
        QueryDeviceServiceDataResponse response;
        try {
            response = client.queryDeviceServiceData(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_SERVICE_DATA_ERROR);
        }

        if (!response.getBody().success) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_SERVICE_DATA_ERROR);
        }

        return response;
    }
}
